home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / cgazv5n4.arc / HUNZIP.C < prev    next >
C/C++ Source or Header  |  1991-09-23  |  5KB  |  160 lines

  1. /*--- Listing 3 ------------------------- HUNZIP.C -------------
  2.  * Author:     Anton Kruger,   5 October, 1990
  3.  *
  4.  * Copyright (c) Truda Software
  5.  *
  6.  * Source code may be freely used if authorship is acknowledged.
  7.  * Object code form may be used freely.
  8.  *
  9.  * Description:   Contains routines to decompress a file that
  10.  *                has been  Huffman encoded with huff_zip.c
  11.  *
  12.  * Compilers:     Turbo C++ 1.0, MSC 6.0
  13.  *
  14.  * Memory models: Any.
  15.  *
  16.  * Compile time switches:
  17.  *                MAIN  - if defined, a driver is provided
  18.  *-------------------------------------------------------------*/
  19.  
  20. #include <stdio.h>
  21. #include "huff.h"
  22.  
  23. int   huff_unzip(char *infile,char *outfile);
  24. void  error(char *s);
  25.  
  26. #if defined(MAIN)
  27. #include <stdlib.h>
  28. #endif
  29.  
  30. #if defined(MAIN)
  31. /*  A small driver for the Huffman decompression routine */
  32. void main(int argc, char* argv[])
  33. {
  34.     int i;
  35.  
  36.     if (argc < 3)
  37.         error("Usage: HUNZIP infile outfile");
  38.     else{
  39.         i = huff_unzip(argv[1],argv[2]);
  40.         switch (i){
  41.             case -1:
  42.                 error("could not open input file...");
  43.                 break;
  44.             case -2:
  45.                 error("could not open output file...");
  46.                 break;
  47.             case -3:
  48.                 error("input not a compressed file...");
  49.                 break;
  50.             case -4:
  51.                 error("input not a Huffman compressed file...");
  52.                 break;
  53.             case -5:
  54.                 error
  55.                 ("incorrect version of decompression program.");
  56.                 break;
  57.             default:
  58.                 ;
  59.         }
  60.     }
  61.     exit(0);
  62. }
  63. #endif
  64.  
  65. int huff_unzip(char *infile,char *outfile)
  66. {
  67.     /*
  68.      * This routine decodes a file "infile" that has been
  69.      * compressed by the companion routine, huff_zip.c.
  70.      * The output is written to the file "outfile".
  71.      *
  72.      * Return values:
  73.      *                  0:   normal return
  74.      *                 -1:   could not open "infile"
  75.      *                 -2:   could not open "outfile"
  76.      *                 -3:   first ID byte invalid
  77.      *                 -4:   second ID byte invalid
  78.      *                 -5:   third ID byte invalid    */
  79.  
  80.     FILE     *fp1;
  81.     FILE     *fp2;
  82.     char     byte;
  83.     int      ib,node;
  84.     int      root;         /* Location of the root of
  85.                                 the Huffman tree */
  86.     unsigned long decoded; /* Counts the number of
  87.                                 decoded characters  */
  88.  
  89.     /* Open I/O files with enlarged buffers for efficiency */
  90.  
  91.     if ((fp1 = fopen(infile,"r+b")) != NULL)
  92.         setvbuf(fp1,NULL,_IOFBF,BUFFER_SIZE);
  93.     else
  94.         return(-1);
  95.     if ((fp2 = fopen(outfile,"w+b")) != NULL)
  96.         setvbuf(fp2,NULL,_IOFBF,BUFFER_SIZE);
  97.     else{
  98.         fclose(fp1);
  99.         return(-2);
  100.     }
  101.  
  102.     /* Check input file header for characters "CH1" */
  103.  
  104.     if (getc(fp1) != 'C')
  105.         { fclose(fp1); fclose(fp2); return(-3); }
  106.     if (getc(fp1) != 'H')
  107.         { fclose(fp1); fclose(fp2); return(-4); }
  108.     if (getc(fp1) != '1')
  109.         { fclose(fp1); fclose(fp2); return(-5); }
  110.  
  111.     /* Read Huffman tree from input file */
  112.  
  113.     fread(&nchars,sizeof(nchars),1,fp1);
  114.     fread(&root,sizeof(root),1,fp1);
  115.     fread(left_son,sizeof(left_son[1]),root+1,fp1);
  116.     fread(right_son,sizeof(right_son[1]),root+1,fp1);
  117.     fread(&nsymbols,sizeof(nsymbols),1,fp1);
  118.     fread(symbol,sizeof(symbol[1]),nsymbols,fp1);
  119.  
  120.     /* Decompress the input file */
  121.  
  122.     decoded = 0;
  123.     node = root;
  124.     while(decoded != nchars) {
  125.                     /* Get a byte from compressed file   */
  126.         byte = (char)getc(fp1);
  127.                     /* Scan all bits in byte             */
  128.         for (ib=7; ib>=0; ib--){
  129.             if (btest(byte,ib))
  130.                     /* bit ib set ?, select left node    */
  131.                 node = left_son[node];
  132.             else
  133.                     /* bit ib clear ?, select right node */
  134.                 node = right_son[node];
  135.                     /* Have reached a terminal node      */
  136.             if (left_son[node] == NONE){
  137.                     /* Write the decoded symbol          */
  138.                 putc(symbol[node],fp2);
  139.                 if (++decoded == nchars)
  140.                     /* Stop if all chars are decoded     */
  141.                     break;
  142.                 else
  143.                 /* Restart decoding at root of tree  */
  144.                     node = root;
  145.             }
  146.         }
  147.     }
  148.  
  149.     /* Close files and return */
  150.  
  151.     fclose(fp1);
  152.     fclose(fp2);
  153.     return(0);
  154. }
  155.  
  156. void error(char *s)
  157. {
  158.     fprintf(stderr,"Error: %s\n",s);
  159.     exit(-1);
  160. }